package com.example.zyl.common.query.aspect;

import com.example.zyl.common.exception.ServiceException;
import com.example.zyl.common.query.annotation.ApiDataSource;
import com.example.zyl.common.utils.constant.Constant;
import com.example.zyl.common.utils.context.DynamicDataSourceContextHolder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

@Component
@Slf4j
@Aspect
@RequiredArgsConstructor
public class DataSourceAspect {

    @Around(value = "@annotation(com.example.zyl.common.query.annotation.ApiDataSource) ||" +
            "@within(com.example.zyl.common.query.annotation.ApiDataSource)")
    public Object around(ProceedingJoinPoint joinPoint) {

        //获取监听方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        // 获取执行方法所在的类
        Class<?> targetClass = signature.getDeclaringType();

        String name = Constant.DEFAULT_DBNAME;
        // 获取类上的注解
        ApiDataSource classAnnotation = targetClass.getAnnotation(ApiDataSource.class);

        //获取方法上的注解
        ApiDataSource apiDataSource = signature.getMethod().getAnnotation(ApiDataSource.class);
        //如果类上有注解，则使用类上的注解，否则使用方法上的注解

        if (null != classAnnotation) {
            name = classAnnotation.name();
        }

        if (null != apiDataSource) {
            name = apiDataSource.name();
        }

        Object result = null;

        try {
            // 设置当前数据源
            DynamicDataSourceContextHolder.setDataSourceType(name);

            // 继续执行目标方法
            result = joinPoint.proceed();
        } catch (Throwable throwable) {
            log.error("执行切换数据源失败，出现异常 ====> [{}]", throwable.getMessage());
            throw new ServiceException(throwable.getMessage());
        } finally {
            // 清理当前数据源，恢复默认状态等操作
            DynamicDataSourceContextHolder.clearDataSourceType();
        }

        return result;
    }

}
